<?php

if (!function_exists('json_encode')) include('json.php');

class JSel{
 protected $name;
 protected $js;
 
 function JSel($n){
  $this->name=$n;
 }
 
 function out(){
  return "document.getElementById('".$this->name."').".$this->js;
 }
 
 public function __toString(){
  return $this->out()."; \n";
 }
 
 function __set($key,$n){
  $this->js=$key."='".addslashes($n)."'";
 }
} 

class JStyle extends JSel{
 function out(){
  return "document.getElementById('".$this->name."').style.".$this->js;
 }
}

/**
*
* trida JS - osefovava odpovedi z RPC procedur smerem do JS
*
**/

class JS {

 private $output;
 private $elements;
 private $elcounts;
 
 function JS(){
  $this->output=array();
  $this->elements=array();
  $this->elcounts=0;
 }
 
 function alert($txt){
  $this->output[]="alert('".addslashes($txt)."');";
 }
 
 function element($id){
   $element=new JSel($id);
   $this->elements[$this->elcounts]=$element;
   $this->output[]=$element;
   $this->elcounts++;
   return $element;
 }

 function style($id){
   $element=new JStyle($id);
   $this->elements[$this->elcounts]=$element;
   $this->output[]=$element;
   $this->elcounts++;
   return $element;
 }
 
 //alias
 function getElementById($id){
  return $this->element($id);
 }

 function out(){
  $s='';
  foreach ($this->output as $out) $s.=$out;
  return $s;
 }
 
 //alias
 function __toString(){return $this->out();}

}

/**
*
* funkce s JS headerem
*
**/

function JSheader(){

?>
// json.js 2007-03-20 Public Domain

if(!Object.prototype.toJSONString){Array.prototype.toJSONString=function(){var a=['['],b,i,l=this.length,v;function p(c){if(b){a.push(',')}a.push(c);b=true}for(i=0;i<l;i+=1){v=this[i];switch(typeof v){case'object':if(v){if(typeof v.toJSONString==='function'){p(v.toJSONString())}}else{p("null")}break;case'string':case'number':case'boolean':p(v.toJSONString())}}a.push(']');return a.join('')};Boolean.prototype.toJSONString=function(){return String(this)};Date.prototype.toJSONString=function(){function f(a){return a<10?'0'+a:a}return'"'+this.getFullYear()+'-'+f(this.getMonth()+1)+'-'+f(this.getDate())+'T'+f(this.getHours())+':'+f(this.getMinutes())+':'+f(this.getSeconds())+'"'};Number.prototype.toJSONString=function(){return isFinite(this)?String(this):"null"};Object.prototype.toJSONString=function(){var a=['{'],b,k,v;function p(c){if(b){a.push(',')}a.push(k.toJSONString(),':',c);b=true}for(k in this){if(this.hasOwnProperty(k)){v=this[k];switch(typeof v){case'object':if(v){if(typeof v.toJSONString==='function'){p(v.toJSONString())}}else{p("null")}break;case'string':case'number':case'boolean':p(v.toJSONString())}}}a.push('}');return a.join('')};(function(f){var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};f.parseJSON=function(c){try{if(/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(this)){var j=eval('('+this+')');if(typeof c==='function'){function walk(a,b){if(b&&typeof b==='object'){for(var i in b){if(b.hasOwnProperty(i)){b[i]=walk(i,b[i])}}}return c(a,b)}j=walk('',j)}return j}}catch(e){}throw new SyntaxError("parseJSON");};f.toJSONString=function(){if(/["\\\x00-\x1f]/.test(this)){return'"'+this.replace(/([\x00-\x1f\\"])/g,function(d,e){var c=m[e];if(c){return c}c=e.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16)})+'"'}return'"'+this+'"'}})(String.prototype)}


function _PHP_GetXmlHttp() {
  var xmlhttp = false;
  if (window.XMLHttpRequest)
  {
    xmlhttp = new XMLHttpRequest()
  }
  else if (window.ActiveXObject)
  {
    try
    {
      xmlhttp = new ActiveXObject("Msxml2.XMLHTTP")
    } catch (e) {
      try
      {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
      } catch (E) {
        xmlhttp=false
      }
    }
  }
  return xmlhttp;
}

function _PHP_AjaxCall(url,meth,par){
  var xmlhttp = new _PHP_GetXmlHttp();
  if (xmlhttp)
  {
    xmlhttp.onreadystatechange = 
            function ()
            {
              if (xmlhttp && xmlhttp.readyState==4)
              {
                if (xmlhttp.status==200)
                {
                  var response = xmlhttp.responseText;
                  eval(response);
                } 
              }
            }
    xmlhttp.open("GET",url+'?ajax=1&method='+meth+'&'+par,true);
    xmlhttp.send(null);
  }
}

function _PHP_AjaxGet(url,meth,par,json){
  var xmlhttp = new _PHP_GetXmlHttp();
  if (xmlhttp)
  {
    xmlhttp.open("GET",url+'?ajax=1&method='+meth+'&'+par,false);
    xmlhttp.send(null);
    if (json) return /*eval('(' + xmlhttp.responseText + ')');*/ xmlhttp.responseText.parseJSON();
    return xmlhttp.responseText;
  }
}


<? }



class JSRPC {
 private $methods;
 private $functions;
 private $json;
 protected $response;
 private $debug;
 
 function JSRPC(){
  $this->methods=array();
  $this->functions=array();
  $this->json=array();
  $this->debug=0;
 }
 
 function registerMethod($metoda,$parametry){
  $this->methods[$metoda]=$parametry;
 }

 function registerFunction($metoda,$parametry){
  $this->functions[$metoda]=$parametry;
 }

 function registerJSONFunction($metoda,$parametry){
  $this->functions[$metoda]=$parametry;
  $this->json[$metoda]=1;
 }


 function debug($dbg){
  $this->debug=$dbg;
 }
 
 static function log($txt){
  $f=fopen('./log.txt','a');
  fwrite($f,$txt."\n");
  fclose($f);
 }

 static function getpars($p){
  $par=explode(',',$p);
  $np=array();
  
  foreach($par as $x){
   if (strpos($x,'[]')) {
    $x=trim(str_replace('[]','',$x));
//    $np[]=json_decode(stripslashes($_GET[$x]));
    $np[]='"'.str_replace("\\'","'",$_GET[$x]).'"';
   } else {
    $np[]='"'.str_replace("\\'","'",$_GET[$x]).'"';
   }
  }
  

  return join(',',$np);
 }

static function jspar($p){
  if (!trim($p)) return '""';
  $par=explode(',',$p);
  $np=array();
  
  foreach($par as $x){
   if (strpos($x,'[]')) {
    $x=trim(str_replace('[]','',$x));
    $np[]='"'.$x.'="+encodeURIComponent('.$x.'.toJSONString())';
   } else {
    $np[]='"'.$x.'="+encodeURIComponent('.$x.')';
   } 
  }
  
  $pars=join('+"&"+',$np);
  $pars=str_replace('"+"','',$pars);
  return $pars;
}

 function toJS(){ 
  $s='';
  foreach ($this->methods as $m=>$p){
  $pars=self::jspar($p);
  $p=str_replace('[]','',$p);
  $s.='function PHP_'.$m.'('.$p.'){_PHP_AjaxCall("http://test/jsrpc/rpc.php","'.$m.'",'.$pars.');}';
  }
  foreach ($this->functions as $m=>$p){
  $pars=self::jspar($p);
  $p=str_replace('[]','',$p);
  if (isset($this->json[$m])) {
   $s.='function PHP_'.$m.'('.$p.'){return _PHP_AjaxGet("http://test/jsrpc/rpc.php","'.$m.'",'.$pars.',true);}';
  } else {
   $s.='function PHP_'.$m.'('.$p.'){return _PHP_AjaxGet("http://test/jsrpc/rpc.php","'.$m.'",'.$pars.',false);}';
  } 
  }
  return $s;
 }

static function phppar($p){
  if (!trim($p)) return '';
  $par=explode(',',$p);
  $np=array();
  
  foreach($par as $x){
   //$np[]='"'.$x.'="+encodeURIComponent('.$x.')';
   $np[]='$'.str_replace('[]','',$x);
  }
  
  $pars=join(',',$np);
  $pars=str_replace('"+"','',$pars);
  return $pars;
}
 
 
 static function phpjson($p){
  if (!trim($p)) return '';
  $par=explode(',',$p);
  $np=array();
  
  foreach($par as $x){
   if (!strpos($x,'[]')) continue;
   $xx=str_replace('[]','',$x);
   $np[]=' $'.$xx.'=json_decode($'.$xx.');'."\n";
  }
  if (!count($np)) return '';
  $pars=join('',$np);
  return $pars;
}
 function toPHP(){ 
  $s="class myJSRPC extends JSRPC{\n";
  foreach ($this->methods as $m=>$p){
  $pars=self::phppar($p);
  $s.="/**\n * method: $m\n **/\n";
  $s.='function PHP_'.$m.'('.$pars."){\n\n \$this->alert('ahoj');\n}\n\n";
  }
  foreach ($this->functions as $m=>$p){
  $pars=self::phppar($p);
  $s.="/**\n * function: $m\n **/\n";
  $s.='function PHP_'.$m.'('.$pars."){\n".self::phpjson($p)."\n return 0;\n}\n\n";
  }
  $s.="} //end of myJSRPC class definition\n\n\$rpc=new myJSRPC();\n\n//Your registerXXX goes here!\n\n\$rpc->run(); //main executive method";
  return $s;
 }
 
 /*
 * shortcuts pro nektere RESPONSE
 */
 
 function alert($txt){
  if ($this->response) $this->response->alert($txt);
 }
 
 function getElementById($txt){
  if ($this->response) return $this->response->element($txt);
 }
 function style($txt){
  if ($this->response) return $this->response->style($txt);
 }
 
 /**
 *executive engine
 **/
 
 function run(){
 
 if (isset($_GET['method'])){

  $metoda=preg_replace('/\W/i','',$_GET['method']);
 
  if (!isset($this->methods[$metoda])
  && !isset($this->functions[$metoda])
  ) {
   echo 'alert("Undefined method '.addslashes($metoda).'");';
  }
 
  if ($this->debug){
  self::log(print_r($_GET,true));
  }
  
  if (isset($this->methods[$metoda])){
  $this->response=new JS();
  $pars=$this->methods[$metoda];
  $given=self::getpars($pars);
  $volani='$this->'.$metoda.'('.$given.');';
  if ($this->debug){self::log($volani);}

  eval($volani);
  echo $this->response->out();
  }
  
  if (isset($this->functions[$metoda])){
  $pars=$this->functions[$metoda];
  $given=self::getpars($pars);
  $volani='$result=$this->'.$metoda.'('.$given.');';
  if ($this->debug){self::log($volani);}

  eval($volani);
  if (isset($this->json[$metoda])) echo json_encode($result);
  else echo $result;
  }
  die();
 } 

 if (isset($_GET['js'])){
  if (!isset($_GET['noheader'])) JSheader();
  echo $this->toJS();
 die();
 } 

 if (isset($_GET['php'])){
  header('Content-Type: text/plain');
  echo $this->toPHP();
 die();
 } 
 
 echo 'NO PARAMETER GIVEN!';
 
 }
 
}

?>